<template>
    <view @touchmove.stop.prevent="()=>false">
        <view class="drag"
            :style="{left,top,width:btnWidth + 'rpx',height:btnHeight  + 'rpx',zIndex}"
            :class="{'drag-transition':haveTransition}"
            @click="btnClick"
            @touchstart="onTouchstart"
            @touchmove="onTouchmove"
            @touchend="onTouchend">
            <slot>
                <view class="item"></view>
            </slot>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            btnWidth: {
                type: [String, Number],
                default: 100
            },
            btnHeight: {
                type: [String, Number],
                default: 100
            },
            zIndex: {
                type: [String, Number],
                default: 100
            },
            // 是否开启吸附
            adsorb: {
                type: Boolean,
                default: true
            },
            // 边界
            boundary: {
                type: Object,
                default: () => {
                    return {
                        top: 0,
                        left: 0,
                        bottom: 0,
                        right: 0,
                    }
                }
            },
            // 初始化位置
            initLocation: {
                type: Object,
                default: () => {}
            }
        },
        data() {
            return {
                left: 0,
                top: 0,
                screenWidth: uni.getSystemInfoSync().screenWidth,
                topBoundary: 0,
                bottomBoundary: 0,
                isOpenRefresh: false,
                haveTransition: false,
            }
        },
        computed: {
            halfWidth() {
                return uni.upx2px(this.btnWidth / 2)
            },
            halfHeight() {
                return uni.upx2px(this.btnHeight / 2)
            },
            boundaryL() {
                return uni.upx2px(this.boundary?.left ?? 0) + this.halfWidth
            },
            boundaryR() {
                return this.screenWidth - (uni.upx2px(this.boundary?.right ?? 0)) - this.halfWidth
            },
            boundaryT() {
                return uni.upx2px(this.boundary?.top ?? this.topBoundary) + this.halfWidth
            },
            boundaryB() {
                return this.bottomBoundary - (uni.upx2px(this.boundary?.bottom ?? 0)) - this.halfWidth
            }
        },
        created() {
            this.calcBoundary()
            this.initPosition()
        },
        mounted() {
            // #ifdef APP-PLUS
            const pages = getCurrentPages()
            const page = pages[pages.length - 1]
            const currentWebview = page.$getAppWebview()
            this.isOpenRefresh = !!currentWebview.getStyle()?.pullToRefresh?.support
            // #endif
        },
        methods: {
            // 计算边界情况
            calcBoundary() {
                const { statusBarHeight, windowHeight } = uni.getSystemInfoSync()
                // 顶部默认边界
                this.topBoundary = statusBarHeight
                // 底部默认边界, 最底部的位置为, windowHeight,可使用窗口高度,也就是有tabbar的就排除了tabbar的高度，没有就到屏幕最底部
                this.bottomBoundary = windowHeight
            },
            // 初始化位置
            initPosition() {
                const { screenWidth, windowHeight } = uni.getSystemInfoSync()
                const initTop = isNaN(uni.upx2px(this.initLocation?.top)) ? windowHeight - uni.upx2px(this.btnWidth) : uni.upx2px(this.initLocation?.top)
                const initLeft = isNaN(uni.upx2px(this.initLocation?.left)) ? screenWidth - uni.upx2px(this.btnHeight) : uni.upx2px(this.initLocation?.left)
                this.top = initTop + 'px'
                this.left = initLeft + 'px'
            },
            btnClick() {
                this.$emit('btnClick')
            },
            onTouchstart(e) {
                this.adsorb && (this.haveTransition = false)
                // #ifdef APP-PLUS
                this.isOpenRefresh && this.isRefresh(false)
                // #endif
            },
            onTouchmove(e) {
                let { clientX, clientY } = e.touches[0]
                
                // x轴边界情况处理
                clientX = Math.max(this.boundaryL, Math.min(clientX, this.boundaryR))
                // y轴边界情况处理
                clientY = Math.max(this.boundaryT, Math.min(clientY, this.boundaryB))
                
                // 减去一半的宽高是为了拖拽时,触点位于按钮的中间
                this.left = clientX - this.halfWidth + 'px'
                this.top = clientY - this.halfHeight + 'px'
            },
            onTouchend(e) {
                // #ifdef APP-PLUS
                this.isOpenRefresh && this.isRefresh(true)
                // #endif
                if (this.adsorb) {
                    this.haveTransition = true
                    let { clientX } = e.changedTouches[0]
                    const { screenWidth } = uni.getSystemInfoSync()
                    // 转换为px
                    const boundaryL = uni.upx2px(this.boundary?.left ?? 0)
                    const boundaryR = screenWidth - uni.upx2px(this.boundary?.right ?? 0) - uni.upx2px(this.btnWidth)
                    this.left = (screenWidth / 2) > clientX ? boundaryL + 'px' : boundaryR + 'px'
                }
            },
            // 是否开启页面的刷新，只在app端有效
            isRefresh(refresh) {
                const pages = getCurrentPages()
                const page = pages[pages.length - 1]
                const currentWebview = page.$getAppWebview()
                // 动态修改页面刷新
                currentWebview.setStyle({
                    pullToRefresh: {
                        support: refresh,
                    }
                })
            }
        }
    }
</script>

<style scoped lang="scss">
    .drag {
        position: fixed;
        border-radius: 100%;
        overflow: hidden;
    }

    .item {
        width: 100%;
        height: 100%;
        background-color: #ffd939;
        position: relative;

        &:before {
            content: '';
            width: 8rpx;
            height: 40%;
            background: black;
            position: absolute;
            left: calc(50% - 4rpx);
            top: 30%;
            border-radius: 10rpx;
        }

        &::after {
            content: '';
            width: 40%;
            height: 8rpx;
            background: black;
            position: absolute;
            left: 30%;
            top: calc(50% - 4rpx);
            border-radius: 10rpx;
        }
    }
    .drag-transition {
        transition: all 0.2s;
    }
</style>